import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

public class RedPacket {
    private static BigDecimal amount; // 红包总金额
    private static BigDecimal totalGrabbed = BigDecimal.ZERO; // 已抢金额总和
    private static final Object lock = new Object(); // 锁对象，用于同步
    private static Stack<BigDecimal> stack = new Stack<>();
    private static Set<String> grabbedThreads = ConcurrentHashMap.newKeySet(); // 已抢红包的线程集合
    private static List<Student> students = new ArrayList<>(); // 学生列表
    private static Map<Student, BigDecimal> results = new HashMap<>(); // 存储抢红包结果
    private static final double maxNum = 100000;


    public RedPacket(BigDecimal amount) {
        RedPacket.amount = amount;
    }

    // 读取学生信息
    private static void readStudentsFromFile(String filename) throws IOException {
        try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
            String line;
            while ((line = reader.readLine()) != null) {
                String[] parts = line.split("\\s+");
                if (parts.length == 3) {
                    students.add(new Student(parts[0], parts[1], parts[2]));
                }
            }
        }
    }

    private static void assignment(int parts) {
        Random random = new Random();
        BigDecimal remaining = amount;
        BigDecimal minAmount = BigDecimal.valueOf(0.01); // 设置最小金额为0.01元

        // 首先确保每个人至少能获得最小金额
        BigDecimal guaranteedMin = minAmount.multiply(BigDecimal.valueOf(parts));
        if (amount.compareTo(guaranteedMin) < 0) {
            throw new IllegalArgumentException("总金额不足以保证每个人都能获得最小金额");
        } else if (amount.compareTo(guaranteedMin) == 0) {
            for (int i = 0; i < parts; i++) {
                stack.push(minAmount);
            }
            return;
        }

        for (int i = 0; i < parts - 1; i++) {
            // 计算二倍均值
            // 将剩余金额除以剩余红包数量，然后乘以 2
            BigDecimal maxAmount = remaining.divide(BigDecimal.valueOf(parts - i), 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(2));
            // 生成一个随机金额, 介于最大值最小值之间
            BigDecimal randomAmount = BigDecimal.valueOf(random.nextDouble()).multiply(maxAmount.subtract(minAmount)).add(minAmount).setScale(2, RoundingMode.HALF_UP);
            randomAmount = randomAmount.max(minAmount); // 确保不少于最小金额
            stack.push(randomAmount);
            remaining = remaining.subtract(randomAmount);
        }

        // 分配最后一个红包
        stack.push(remaining.setScale(2, RoundingMode.HALF_UP));
    }

    // 抢红包的方法
    public static void grab(Student student) {
        if (grabbedThreads.add(student.getStudentName())) { // 使用原子操作检查并更新集合
            synchronized (lock) {
                if (!stack.isEmpty()) {
                    BigDecimal grabbed = stack.pop();
                    results.put(student, grabbed);
                    totalGrabbed = totalGrabbed.add(grabbed);
                } else {
                    results.put(student, BigDecimal.ZERO);
                }
            }
        }
    }

    // 将结果写入文件
    private static void writeResultsToFile(String filename) throws IOException {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(filename))) {
            for (Map.Entry<Student, BigDecimal> entry : results.entrySet()) {
                writer.write(entry.getKey().getStudentName() + " 抢到了 " + entry.getValue() + "\n");
            }
        }
    }

    // 检查是否抢完，并打印结果
    public static void checkAndPrintResult() {
        System.out.println("所有线程抢到的金额总和：" + totalGrabbed);
    }

    public static void main(String[] args) throws InterruptedException, IOException {
        Scanner scanner = new Scanner(System.in);

        double totalAmount;
        while (true) {
            System.out.print("请输入红包总金额：");
            totalAmount = scanner.nextDouble();
            if (totalAmount <= maxNum) {
                break;
            }
            System.out.println("红包最大不能超过：" + maxNum);
        }

        System.out.print("请输入抢红包的人数：");
        int people = scanner.nextInt();

        // 读取学生信息
        readStudentsFromFile("人员信息.txt");

        if (people > students.size()) {
            throw new IllegalArgumentException("抢红包的人数不能大于学生总数");
        }

        new RedPacket(BigDecimal.valueOf(totalAmount)); // 创建红包实例
        assignment(people); // 分配红包金额

        synchronized (lock) {
            System.out.println("红包数量：" + stack.size());
            System.out.println("分配后的红包stack: " + stack);
        }

        // 创建线程抢红包
        Thread[] threads = new Thread[students.size()];
        AtomicInteger index = new AtomicInteger(0);
        for (int i = 0; i < threads.length; i++) {
            int finalI = i;
            threads[i] = new Thread(() -> grab(students.get(finalI)));
            threads[i].start();
        }

        // 等待所有线程执行完毕
        for (Thread thread : threads) {
            thread.join();
        }

        // 检查并打印结果
        checkAndPrintResult();

        // 将结果写入文件
        writeResultsToFile("抢红包结果.txt");

        // 关闭资源
        scanner.close();
    }
}